package  cn.klaw.utils;

import cn.klaw.util.ThreadPoolExecutorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Future;
import java.util.function.Supplier;

/**
 * 异步FEIGN请求， 把当前REQUEST的HEADER存入新线程中， 在新线程中调用feign请求， FeignConfig 中取当前headers发送到新服务
 * 使用方式：
 * 1、直接调用set设置Header, Feign请求全部调用完之后调用clear清除线程变量
 * 2、调用asyncFeign、sendFeign 调用完后自动清除线程变量
 */
//@ConditionalOnBean(ThreadPoolTaskExecutor.class)
@Component
@Slf4j
public class FeignHolder {
    private static ThreadLocal<Map<String, String>> feignHeader = new ThreadLocal<>();


    public static void set(Map<String, String> headers){
        TreeMap map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        map.putAll(headers);
        feignHeader.set(map);
    }

    public static Map<String, String> get(){
        return feignHeader.get();
    }

    public static void clear(){
        feignHeader.remove();
    }

    /**
     * Async异步发送请求, 完成后清空线程变量
     *
     * @param headers
     * @param supplier
     * @return
     */
    public static Future<?> asyncFeign(Map<String, String> headers, Supplier supplier){
        return ThreadPoolExecutorUtil.getExecutor().submit(()-> sendFeign(headers, supplier));
    }

    /**
     * 同步发送请求, 完成后清空线程变量
     * @param headers
     * @param supplier
     */
    public static <R> R sendFeign(Map<String, String> headers, Supplier<R> supplier){
        try{
            set(headers);
            return supplier.get();
        }catch(Exception e){
            log.error("同步发送Feign请求失败", e);
            return null;
        }finally{
            clear();
        }
    }

}
